package com.load.ctrls.imp;

import java.util.*;

import org.apache.log4j.Logger;

import com.database.daos.*;
import com.database.objects.*;
import com.google.common.collect.*;
import com.load.ctrls.IContributionCtrl;
import com.metrics.calculators.*;
import com.metrics.objects.*;

public class ContributionCtrl implements IContributionCtrl {

	private static Logger logger = Logger.getLogger("load.repository");

	private static final long serialVersionUID = -6843027034211435186L;

	private IContributionDao contributionDao;

	private ISumDao sumDao;

	private MetricCalculatorMap metricCalculatorMap;

	@Override
	public void calculateContributions(Developer developer, Repository repository, List<Element<?, ?>> elements) {
		logger.info("DEVELOPER: " + developer.getName() + " - START CALCULATE CONTRIBUTION");
		Multimap<String, Element<?, ?>> elementsMap = HashMultimap.create();
		for (Element<?, ?> element : elements) {
			elementsMap.put(element.getDate(), element);
		}

		for (String date : elementsMap.keySet()) {
			for (Type type : repository.getTypes()) {
				for (Status status : repository.getStatus()) {
					logger.info("DEVELOPER: " + developer.getName() + " - COUNT TYPE: " + type.toString() + " - STATUS: " + status.toString());
					Contribution contribution = constructContribution(developer, date, type, status);

					for (Metric metric : repository.getMetrics()) {
						logger.info("DEVELOPER: " + developer.getName() + " - COUNT TYPE: " + type.toString() + " - STATUS: " + status.toString() + " - METRIC" + metric.toString());
						MetricCalculator calculator = metricCalculatorMap.get(metric);
						calculator.calculate(developer, date, type, status, contribution);
					}
					contributionDao.saveElement(contribution);
				}
			}
		}

		logger.info("DEVELOPER: " + developer.getName() + " - FINISH CALCULATE CONTRIBUTION");
	}

	private Contribution constructContribution(Developer developer, String date, Type type, Status status) {
		Contribution contribution = contributionDao.getByDeveloperAndDateAndTypeAndStatus(developer, date, type, status);
		if (contribution == null) {
			contribution = new Contribution(developer, date, type, status);
		}
		return contribution;
	}

	@Override
	public Map<Type, Map<Status, Double>> findSummariesByProject(Project project, Repository repository) {
		Map<Type, Map<Status, Double>> summaries = new HashMap<Type, Map<Status, Double>>();
		for (Type type : repository.getTypes()) {
			Map<Status, Double> valueMap = new HashMap<Status, Double>();
			for (Status status : repository.getStatus()) {
				Double value = sumDao.getSumNumberContributionsByProjectAndTypeAndStatus(project, type, status, Options.START_DATE_DEFAULT, Options.FINISH_DATE_DEFAULT);
				valueMap.put(status, value);
			}
			summaries.put(type, valueMap);
		}
		return summaries;
	}

	public void setContributionDao(IContributionDao contributionDao) {
		this.contributionDao = contributionDao;
	}

	public void setSumDao(ISumDao sumDao) {
		this.sumDao = sumDao;
	}

	public void setMetricCalculatorMap(MetricCalculatorMap metricCalculatorMap) {
		this.metricCalculatorMap = metricCalculatorMap;
	}

}